/* 
 * Copyright (C) 2013, 2014 lex
 * All Right Reserved.
 *
 * file:	drivers/uart.h
 * history:	2013 Juy 5 created by lex
 */

#ifndef __UART_H__
#define __UART_H__

#include "types.h"
#include "s3c2440.h"

#define NR_UART_PORT_MAX		3

/* 
 * line control register 
 */
union uart_line {
	struct {
		u8 word_len	:2;
		u8 nr_stop	:1;
		u8 parity	:3;
		u8 infrared	:1;
		u8 rsv		:1;

		u8 rsv_data[3];
	} l;

	u32 data;
};

/*
 * control register 
 */
union uart_control {
	struct {
		u8 rx_mode	:2;
		u8 tx_mode	:2;
		u8 brk_signal	:1;	/* send break signal */
		u8 lbk_mode	:1;
		u8 rx_err_int	:1;	/* rx error status intrrupt enable  */
		u8 rx_time_out	:1;

		u8 rx_int_type	:1;	/* rx intrrupt type */
		u8 tx_int_type	:1;
		u8 clock	:2;	/* clk 00,10 = PCLK 01 = UEXTCLK 11 = FLCK/n */
		u8 fclk_div	:4;	/* fclk	divider */

		u8 rsv_data[2];
	} c;
	u32 data;
};

/* 
 * fifo control 
 */
union uart_fifo {
	struct {
		u8 enable	:1;
		u8 rx_reset	:1;
		u8 tx_reset	:1;
		u8 rsv		:1;
		u8 rx_trigger	:2;	/* rx fifo trigger level */
		u8 tx_trigger	:2;	/* tx fifo trigger level */

		u8 rsv_data[3];
	} f;
	u32 data;
};

/*
 * modem control
 */
union uart_modem {
	struct {
		u8 req_send	:1;	/* request to send   */
		u8 rsv		:3;
		u8 afc		:1;	/* auto flow control */
		u8 rsv1		:3;

		u8 rsv_data[3];
	} m;
	u32 data;
};

union uart_tr_stat {
	struct {
		u8	rx_ready	:1;
		u8	tx_empty	:1;
		u8	tsmtr_empty	:1;
		u8	rsv		:5;

		u8	rsv_data[3];
	} tr;

	u32	data;
};

union uart_err_stat {
	struct {
		u8	overrun		:1;
		u8	parity		:1;
		u8	frame		:1;
		u8	brk		:1;
		u8	rsv		:4;

		u8	rsv_data[3];
	} err;

	u32	data;
};

union uart_fifo_stat {
	struct {
		u8	rx_cnt		:6;
		u8	rx_full		:1;
		u8	rsv1		:1;

		u8	tx_cnt		:6;
		u8	tx_full		:1;
		u8	rsv2		:1;

		u8	rsv_data[2];
	} fs;
	u32	data;
};

union uart_modem_stat {
	struct {
		u8	cts	:1;
		u8	rsv1	:3;
		u8	delta	:1;
		u8	rsc2	:3;

		u8	rsv_data[3];
	} ms;
	u32	data;
};

union uart_buf_little {
	struct {
		u8	byte;
		u8	rsv_data[3];
	} b;

	u32 data;
};

union uart_buf_big {
	struct {
		u8	rsv_data[3];
		u8	byte;
	} b;

	u32 data;
};

#define __LITTLE_ENDIAN__	1

struct uart_dev {
	union uart_line		lcr;
	union uart_control	ccr;
	union uart_fifo		fcr;
	union uart_modem	mcr;
	union uart_tr_stat	trsr;
	union uart_err_stat	errsr;
	union uart_fifo_stat	fsr;
	union uart_modem_stat	msr;

#ifdef __LITTLE_ENDIAN__
	union uart_buf_little	tbr;
	union uart_buf_little	rbr;
#else
	union uart_buf_big	tbr;
	union uart_buf_big	rbr;
#endif
	u32	brdiv;
};

#define NR_PRINT_CH_MAX		512

extern void	uart_init(int);
extern u8	uart_getc(int);
extern void    	uart_putc(u8 ch, int);
extern void    	uart_puts(u8 *str, int);
extern void    	uart_printf(int, char *fmt, ...);
extern void    	printf_d(char *fmt, ...);
extern u8	uart_getc_timeout(int, u32 delay);

#endif /* end of __UART_H__ */
